// test_memory_manager.c

#include <stdio.h>
#include <string.h>
#include "_alloc.h"

// 辅助函数：检查内存对齐
int is_aligned(void* ptr, size_t alignment) {
    return ( (size_t) ptr % alignment) == 0;
}

int main(void) {
    printf("=== 自动初始化测试 ===\n");
    // 第一次分配会触发自动初始化

    printf("\n=== 基本分配和释放测试 ===\n");
    int* a = (int*)malloc(sizeof(int));
    if (a) {
        *a = 42;
        printf("Allocated int with value: %d\n", *a);
    } else {
        printf("Failed to allocate memory for int.\n");
    }

    free(a);
    printf("Freed memory for int.\n");

    printf("\n=== calloc 功能测试 ===\n");
    int* arr = (int*)calloc(5, sizeof(int));
    if (arr) {
        printf("Allocated array with values: ");
        int zero_flag = 1;
        for (int i = 0; i < 5; i++) {
            printf("%d ", arr[i]);
            if (arr[i] != 0) zero_flag = 0;
        }
        printf("\n");
        printf("calloc zero initialization %s.\n", zero_flag ? "passed" : "failed");
    } else {
        printf("Failed to allocate memory for array.\n");
    }

    free(arr);
    printf("Freed memory for array.\n");

    printf("\n=== 边界条件测试 ===\n");
    // 尝试分配超过内存池大小的内存
    void* large_ptr = malloc(MEMORY_POOL_SIZE);
    if (large_ptr) {
        printf("Unexpectedly allocated large memory block.\n");
    } else {
        printf("Correctly failed to allocate memory exceeding pool size.\n");
    }

    printf("\n=== 内存碎片测试 ===\n");
    // 分配多个块
    void* ptr1 = malloc(200);
    void* ptr2 = malloc(100);
    void* ptr3 = malloc(150);
    void* ptr4 = malloc(50);

    if (ptr1 && ptr2 && ptr3 && ptr4) {
        printf("Allocated blocks: ptr1, ptr2, ptr3, ptr4.\n");
    } else {
        printf("Failed to allocate multiple blocks.\n");
    }

    // 释放部分块以制造碎片
    free(ptr2);
    printf("Freed ptr2.\n");
    free(ptr4);
    printf("Freed ptr4.\n");

    // 尝试分配一个较大的块，检查是否能利用碎片
    void* ptr5 = malloc(120); // 应该可以放在ptr2的位置
    if (ptr5) {
        if(ptr5 == ptr2) {
            printf("Allocated ptr5 (120 bytes) reusing freed block ptr2.\n");
        } else {
            printf("Allocated ptr5 (120 bytes) at %p, not reusing ptr2.\n", ptr5);
        }
    } else {
        printf("Failed to allocate ptr5 (120 bytes).\n");
    }

    // 释放所有块
    free(ptr1);
    printf("Freed ptr1.\n");
    free(ptr3);
    printf("Freed ptr3.\n");
    free(ptr5);
    printf("Freed ptr5.\n");

    printf("\n=== 重复分配和释放测试 ===\n");
    // 重复分配和释放相同大小的块
    #define REPETITIONS 10
    void* reps[REPETITIONS];
    for (int i = 0; i < REPETITIONS; i++) {
        reps[i] = malloc(50);
        if (reps[i]) {
            memset(reps[i], i, 50); // 填充数据
            printf("Allocated reps[%d] at %p.\n", i, reps[i]);
        } else {
            printf("Failed to allocate reps[%d].\n", i);
        }
    }

    for (int i = 0; i < REPETITIONS; i++) {
        if (reps[i]) {
            free(reps[i]);
            printf("Freed reps[%d].\n", i);
        }
    }

    printf("\n=== 对齐测试 ===\n");
    // 分配多个块并检查对齐
    #define ALIGN_TEST_COUNT 5
    void* align_ptrs[ALIGN_TEST_COUNT];
    size_t alignment = MEMORY_POOL_ALIGNMENT;
    for (int i = 0; i < ALIGN_TEST_COUNT; i++) {
        align_ptrs[i] = malloc(16);
        if (align_ptrs[i]) {
            printf("Allocated align_ptrs[%d] at %p - Alignment %s.\n", i, align_ptrs[i],
                   is_aligned(align_ptrs[i], alignment) ? "OK" : "NOT OK");
        } else {
            printf("Failed to allocate align_ptrs[%d].\n", i);
        }
    }

    for (int i = 0; i < ALIGN_TEST_COUNT; i++) {
        if (align_ptrs[i]) {
            free(align_ptrs[i]);
            printf("Freed align_ptrs[%d].\n", i);
        }
    }

    printf("\n=== 压力测试 ===\n");
    // 大量分配和释放
    #define STRESS_TEST_COUNT 100
    void* stress_ptrs[STRESS_TEST_COUNT];
    for (int i = 0; i < STRESS_TEST_COUNT; i++) {
        size_t size = (i % 20 + 1) * 4; // 4, 8, ..., 80 bytes
        stress_ptrs[i] = malloc(size);
        if (stress_ptrs[i]) {
            memset(stress_ptrs[i], i, size);
        } else {
            printf("Stress test: Failed to allocate block %d of size %zu.\n", i, size);
        }
    }

    // 释放偶数索引的块
    for (int i = 0; i < STRESS_TEST_COUNT; i += 2) {
        if (stress_ptrs[i]) {
            free(stress_ptrs[i]);
            stress_ptrs[i] = NULL;
        }
    }

    // 再次分配
    for (int i = 0; i < STRESS_TEST_COUNT; i++) {
        if (!stress_ptrs[i]) {
            stress_ptrs[i] = malloc(16);
            if (stress_ptrs[i]) {
                memset(stress_ptrs[i], i, 16);
            } else {
                printf("Stress test: Failed to reallocate block %d.\n", i);
            }
        }
    }

    // 释放所有块
    for (int i = 0; i < STRESS_TEST_COUNT; i++) {
        if (stress_ptrs[i]) {
            free(stress_ptrs[i]);
        }
    }
    printf("Completed stress test.\n");

    printf("\n=== 所有测试完成 ===\n");
    return 0;
}
